var GownFullHTMLTextareaAdapter = GownFullObjectAdapter.extend({
	keydown_handler: null,
	keyup_handler: null,
	keypress_handler: null,
	focus_handler: null,
	lostsel_handler: null,
	constructor: function(obj)
	{
		this.base(obj);
	},
	clone: function(obj)
	{
		return new GownFullHTMLTextareaAdapter(obj);
	},
	GetCursorXY: function()
	{
		var offset,pos;

		offset = JSVKBrowserExtension.getSelectionOffset(this.obj);
		pos = JSVKBrowserExtension.getOffset(this.obj);
		pos.x += offset.x;
		pos.y += offset.y;

		return new Array(pos.x,pos.y);
	},
	SendString: function(o,s)
	{
		this.SetFocus();
		this.InsertAtCursor(s);
		return true;
	},
	SetFocus: function()
	{
		if(this.obj.focus) this.obj.focus();
		return true;
	},
	GetCursor: function()
	{
		return null;
	},
	RestoreCursor: function(cur)
	{
		return null;
	},
	AttachHandler: function(keydown_handler,keypress_handler,keyup_handler,focus_handler,lostsel_handler)
	{
		var x = this;

		this.keydown_handler = keydown_handler;
		this.keyup_handler = keyup_handler;
		this.keypress_handler = keypress_handler;
		this.focus_handler = focus_handler;
		this.lostsel_handler = lostsel_handler;

		if(GownFullBrowserDetect.use_key_addEventListener) {
			this.obj.addEventListener("keydown", function(e) { return x.keydown_handler(e); },false);
			this.obj.addEventListener("keypress", function(e) { return x.keypress_handler(e); },false);
			this.obj.addEventListener("keyup", function(e) { return x.keyup_handler(e); },false);
			this.obj.addEventListener("focus",function(e) { return x.focus_handler(e); },false);
			this.obj.addEventListener("mousedown", function(e) { x.lostsel_handler(e); return true; },false);
		}
		else if(GownFullBrowserDetect.use_attachEvent) {
			this.obj.attachEvent("onkeydown", function(e) { return x.keydown_handler(e); });
			this.obj.attachEvent("onkeypress", function(e) { return x.keypress_handler(e); });
			this.obj.attachEvent("onkeyup", function(e) { return x.keyup_handler(e); });
			this.obj.attachEvent("onfocus",function(e) { return x.focus_handler(e); });
			this.obj.attachEvent("onmousedown",function(e) { x.lostsel_handler(e); return true; });
		}
		else {
			this.obj.onkeydown = function() { return x.keydown_handler(window.event); }
			this.obj.onkeypress = function() { return x.keypress_handler(window.event); }
			this.obj.onkeyup = function() { return x.keyup_handler(window.event); }
			this.obj.onfocus = function() { return x.focus_handler(window.event); }
			this.obj.onmousedown = function() { x.lostsel_handler(window.event); return true; }
		}
	},
	GetSelection: function()
	{
		try { // should be happen only on IE
			return document.selection.createRange();
		}
		catch(e) {}
		return true;
	},
	RestoreSelection: function(sel)
	{
		try { // should be happen only on IE
			sel.select();
		}
		catch(e) {}
		return true;
	},

/* 
  The following codes are adopted from DocumentSelection library of JSVK

  Visit http://debugger.ru/demo/projects/virtualkeyboard/demo_inline.html for Virtual Keyboard

wonghang: updated to trunk 345. 2007-10-27
*/

	SetSelection: function(start,end,relative)
	{
		var ot = this.obj.scrollTop;
		var ol = this.obj.scrollLeft;

		if(relative) {
			var st = this.GetSelectionStart();
			end = st+end;
			start = st+start;
		}
		start = (start < 0) ? 0 : start;
		end = (end < start) ? start : end;
		if ('function' == typeof this.obj.setSelectionRange) {
			/*
			*  for Mozilla
			*/
			try {this.obj.setSelectionRange(start, end)} catch (e) {}
		}
		else {
			/*
			*  for IE
			*/
			var range;
			/*
			*  just try to create a range....
			*/
			try {
				range = this.obj.createTextRange();
			} catch(e) {
				try {
					range = document.body.createTextRange();
					range.moveToElementText(this.obj);
				} catch(e) { return false; }
			}
			range.collapse(true);
			range.moveStart("character", start);
			range.moveEnd("character", end - start);
			range.select();
		}
		this.keepScroll(ot,ol);
	},
	GetSelectionStart: function()
	{
		var off;
		try {
			this.obj.document.body.setActive();
			off = Math.abs(document.selection.createRange().moveStart("character", -100000000));
			/*
			*  test for the TEXTAREA's dumb behavior
			*/
			/*
			*  calculate node offset
			*/
			var r = document.body.createTextRange();
			r.moveToElementText(this.obj);
			var sTest = Math.abs(r.moveStart("character",-100000000));
			off -= sTest;
		}
		catch (e) {
			try {
				off = this.obj.selectionStart;
			}
			catch (e) {
				off = 0;
			}
		}
		return off;
	},
	GetSelectionEnd: function()
	{
		var off;
		try {
			this.obj.document.body.setActive();
			off = Math.abs(document.selection.createRange().moveEnd("character", -100000000));
		}
		catch (e) {
			try {
				off = this.obj.selectionEnd;
			}
			catch (e) {
				off = 0;
			}
		}
		return off;
	},
	InsertAtCursor: function(str,keep)
	{
		var ot = this.obj.scrollTop;
		var ol = this.obj.scrollLeft;

		if(!keep) this.DeleteSelection();
		var ret = "";
		var s = this.GetSelectionStart();
		/*
		*  check for IE, because Opera does use \r\n sequence, but calculate positions correctly
		*/
		var tmp = document.selection&&!window.opera?this.obj.value.replace(/\r/g,""):this.obj.value;
		this.obj.value = tmp.substring(0,s)+str+tmp.substring(s,tmp.length);
		s += str.length;
		this.SetSelection(s,s);
		this.keepScroll(ot,ol);
		return s;
	},
	DeleteAtCursor: function(after)
	{
		if(after) this.SetSelection(0,1,true);
		else this.SetSelection(-1,0,true);
		return this.DeleteSelection();
	},
	DeleteSelection: function()
	{
		var ol = this.obj.scrollLeft;
		var ot = this.obj.scrollTop;
		var ret = "";
		var s = this.GetSelectionStart();
		var e = this.GetSelectionEnd();

		if (s!=e) {
			/*
			*  check for IE, because Opera does use \r\n sequence, but calculate positions correctly
			*/
			var tmp = document.selection&&!window.opera?this.obj.value.replace(/\r/g,""):this.obj.value;
			ret = tmp.substring(s,e);
			this.obj.value = tmp.substring(0, s)+tmp.substring(e,tmp.length);
			this.SetSelection(s,s);
		}
		this.keepScroll(ot,ol);
		return ret;
	},
	keepScroll: function(ot,ol)
	{
		if (window.getSelection) {
			var q = this.GetCursorXY();
			var el = this.obj;
			if (el.contentWindow) el = el.contentWindow.document.body;
		
			if (ot>q[1])                      el.scrollTop = q[1];
			else if (ot+el.clientHeight>q[1]) el.scrollTop = ot;
			else                             el.scrollTop = q[1]-el.clientHeight/2; 
		
			if (ol>q[0])                      el.scrollLeft = q[0];
			else if (ol+el.clientWidth>q[0])  el.scrollLeft = ol;
			else                             el.scrollLeft = q[0]-el.clientWidth/2; 
		}
	}
});
